`include "PRV564Config.v"
`include "PRV564Define.v"
//////////////////////////////////////////////////////////////////////////////////////////////////
//  Date    : 2021/7/5                                                                          //
//  Author  : Jack.Pan                                                                          //
//  Desc    : Cycle and Instruction counter unit for PRV564 processor                           //
//  Version : 0.0(Orignal)                                                                      //
//////////////////////////////////////////////////////////////////////////////////////////////////
module Counter(
    input wire              CLKi, ARSTi,        //clock and global reset
    input wire              wb_valid,           //write back is valid (instret + 1)
    //-----------write back to csr---------
    input wire [11:0]       csr_index,
    input wire [`XLEN-1:0]  csr_data,
    input wire              csr_wren,
    //---------
    output reg [`XLEN-1:0]  mcycle, minstret,
    output wire [`XLEN-1:0] mcountinhibit
);
//---------------counter inhibit-------------
reg mcountinhibit_CY, mcountinhibit_IR;
always@(posedge CLKi or posedge ARSTi)begin
    if(ARSTi)begin
        mcountinhibit_CY <= 1'b0;
        mcountinhibit_IR <= 1'b0;
    end
    else if(csr_wren)begin
        if(csr_index == `mrw_mcountinhibit_index)begin
            mcountinhibit_CY <= csr_data[0];
            mcountinhibit_IR <= csr_data[2];
        end
    end
end
assign mcountinhibit = {61'b0,mcountinhibit_IR,1'b0,mcountinhibit_CY};
//---------------performance counter-----------------           Run! Run! Run!
always@(posedge CLKi or posedge ARSTi)begin
    if(ARSTi)begin
        mcycle <= 'h0;
    end
    else if(csr_wren)begin
        if(csr_index == `mrw_mcycle_index)begin
            mcycle <= csr_data;
        end
    end
    else begin
        mcycle <= mcountinhibit_CY ? mcycle : (mcycle + 'd1);
    end
end
always@(posedge CLKi or posedge ARSTi)begin
    if(ARSTi)begin
        minstret <= 'h0;
    end
    else if(csr_wren)begin
        if(csr_index == `mrw_minstret_index)begin
            minstret <= csr_data;
        end
    end
    else if(wb_valid)begin                      //当前有指令写回，记录指令+1
        minstret <= mcountinhibit_IR ? minstret : (minstret + 'd1);
    end
end

endmodule

